﻿using AJWPFAdmin.Core.Components.AJTable.ViewModels;
using AJWPFAdmin.Core.Components.ViewModels;
using AJWPFAdmin.Core.Excel;
using AJWPFAdmin.Core.ExtensionMethods;
using AJWPFAdmin.Core.Utils;
using DocumentFormat.OpenXml.Office2013.Excel;
using DocumentFormat.OpenXml.Spreadsheet;
using Masuit.Tools;
using MaterialDesignExtensions.Controls;
using Prism;
using Prism.Commands;
using Prism.Events;
using Prism.Ioc;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using static AJWPFAdmin.Core.ExceptionTool;

namespace AJWPFAdmin.Core.Components.Views
{
    /// <summary>
    /// AJTable.xaml 的交互逻辑
    /// </summary>
    public partial class AJTable : UserControl
    {
        private SemaphoreSlim _fetchLocker;

        public static DependencyProperty ToolBarVisibilityProperty =
            DependencyProperty.Register(nameof(ToolBarVisibility), typeof(Visibility), typeof(AJTable), new PropertyMetadata(Visibility.Visible));

        public Visibility ToolBarVisibility
        {
            get { return (Visibility)GetValue(ToolBarVisibilityProperty); }
            set { SetValue(ToolBarVisibilityProperty, value); }
        }

        public static DependencyProperty PageSizeSelectorVisibilityProperty =
            DependencyProperty.Register(nameof(PageSizeSelectorVisibility), typeof(Visibility), typeof(AJTable), new PropertyMetadata(Visibility.Visible));

        public Visibility PageSizeSelectorVisibility
        {
            get { return (Visibility)GetValue(PageSizeSelectorVisibilityProperty); }
            set { SetValue(PageSizeSelectorVisibilityProperty, value); }
        }

        public static DependencyProperty JumpPageVisibilityProperty =
            DependencyProperty.Register(nameof(JumpPageVisibility), typeof(Visibility), typeof(AJTable), new PropertyMetadata(Visibility.Visible));

        public Visibility JumpPageVisibility
        {
            get { return (Visibility)GetValue(JumpPageVisibilityProperty); }
            set { SetValue(JumpPageVisibilityProperty, value); }
        }


        public static DependencyProperty ImportOptionsProperty =
            DependencyProperty.Register(nameof(ImportOptions), typeof(AJTableImportOptions), typeof(AJTable), new PropertyMetadata(ImportOptionsPropertyChange));

        public AJTableImportOptions ImportOptions
        {
            get { return (AJTableImportOptions)GetValue(ImportOptionsProperty); }
            set { SetValue(ImportOptionsProperty, value); }
        }

        private static void ImportOptionsPropertyChange(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender is AJTable dataGrid)
            {
                dataGrid.Btn_Import.Visibility
                    = dataGrid.ImportOptions == null ? Visibility.Collapsed : Visibility.Visible;
            }
        }

        public static DependencyProperty RowSelectionProperty =
            DependencyProperty.Register(nameof(RowSelection), typeof(AJTableRowSelection), typeof(AJTable), new PropertyMetadata(RowSelectionPropertyChange));

        public AJTableRowSelection RowSelection
        {
            get { return (AJTableRowSelection)GetValue(RowSelectionProperty); }
            set { SetValue(RowSelectionProperty, value); }
        }

        private static void RowSelectionPropertyChange(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender is AJTable dataGrid)
            {
                dataGrid.CreateRowSelectionColumn();
            }
        }

        public static DependencyProperty EnableRowIndexProperty =
            DependencyProperty.Register(nameof(EnableRowIndex), typeof(bool), typeof(AJTable), new PropertyMetadata(false));

        public bool EnableRowIndex
        {
            get { return (bool)GetValue(EnableRowIndexProperty); }
            set { SetValue(EnableRowIndexProperty, value); }
        }

        public static DependencyProperty FetchOptionsProperty =
            DependencyProperty.Register(nameof(FetchOptions), typeof(AJTableFetchOptions), typeof(AJTable), new PropertyMetadata(FetchOptionsPropertyChange));

        public AJTableFetchOptions FetchOptions
        {
            get { return (AJTableFetchOptions)GetValue(FetchOptionsProperty); }
            set { SetValue(FetchOptionsProperty, value); }
        }

        private static async void FetchOptionsPropertyChange(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender is AJTable dataGrid)
            {
                ((AJTableFetchOptions)e.NewValue).Component = dataGrid;

                if (dataGrid.FetchOptions.FetchOnLoaded)
                {
                    dataGrid.DgHst_Loading.IsOpen = true;

                    await Task.Delay(1000);

                    dataGrid.SearchCmd.Execute("False");
                }
            }
        }

        public static DependencyProperty FormConfigProperty =
            DependencyProperty.Register(nameof(FormConfig), typeof(AJTableSearchFormConfig), typeof(AJTable), new PropertyMetadata(AJTableSearchFormConfig.Default, FormConfigPropertyChanged));

        public AJTableSearchFormConfig FormConfig
        {
            get { return (AJTableSearchFormConfig)GetValue(FormConfigProperty); }
            set { SetValue(FormConfigProperty, value); }
        }

        private static void FormConfigPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender is AJTable dataGrid)
            {
                if (dataGrid.FormConfig != null && dataGrid.FormConfig.Schemas?.Count > 0)
                {
                    dataGrid.DrawerHst_AdvFilterTopContent
                        .ItemsCtrl_AdvFilterItems.ItemsSource = dataGrid.FormConfig.Schemas;
                }

                dataGrid.DrawerHst_AdvFilterTopContent.Btn_Search.Click += (s, e) =>
                {
                    dataGrid.ExecuteSearchCmd("False");
                };
                dataGrid.DrawerHst_AdvFilterTopContent.Btn_Reset.Click += (s, e) =>
                {
                    dataGrid.ExecuteSearchCmd("True");
                };
            }
        }


        public static DependencyProperty PaginationProperty =
            DependencyProperty.Register(nameof(Pagination), typeof(AJTablePagination), typeof(AJTable), new PropertyMetadata(new AJTablePagination()));

        public AJTablePagination Pagination
        {
            get { return (AJTablePagination)GetValue(PaginationProperty); }
            set { SetValue(PaginationProperty, value); }
        }

        public static DependencyProperty ColumnsProperty =
            DependencyProperty.Register(nameof(Columns), typeof(List<AJTableColumnItem>), typeof(AJTable), new PropertyMetadata(new List<AJTableColumnItem>(), ColumnsPropertyChanged));

        public List<AJTableColumnItem> Columns
        {
            get { return (List<AJTableColumnItem>)GetValue(ColumnsProperty); }
            set { SetValue(ColumnsProperty, value); }
        }

        private static void ColumnsPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender is AJTable dataGrid)
            {
                dataGrid.ColumnsPropertyChanged(e);
            }
        }

        private void ColumnsPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            if (Columns == null || !Columns.Any())
            {
                return;
            }

            DG_Table.Columns.RemoveWhere(p => p is not AJDataGridCheckBoxTemplateColumn);
            DG_Fixed.Columns.Clear();
            //var styleCenter = new Style(typeof(TextBlock));
            //styleCenter.Setters.Add(new Setter(TextBlock.HorizontalAlignmentProperty, HorizontalAlignment.Center));
            //styleCenter.Setters.Add(new Setter(TextBlock.VerticalAlignmentProperty, VerticalAlignment.Center));

            var hasFixedCol = Columns.Any(p => p.Fixed == AJTableColumnFixedType.Left);

            if (EnableRowIndex)
            {
                Columns.Insert(0, new AJTableColumnItem
                {
                    Title = "序号",
                    DataIndex = $"ColumnIndex_{Guid.NewGuid().ToString("N")}",
                    Width = new DataGridLength(100, DataGridLengthUnitType.SizeToCells, 60, 60),
                    CustomTemplate = new AJTableCustomTemplate
                    {
                        Key = "ColumnIndex"
                    },
                    Fixed = hasFixedCol ? AJTableColumnFixedType.Left : null,
                    IsExport = false
                });
            }


            DG_Table.Columns.AddRange(Columns.Where(p =>(p.Fixed == null || p.Fixed == AJTableColumnFixedType.Left))
                .Select(c => c.CreateColumn()));

            DG_Fixed.Columns.AddRange(Columns.Where(p => p.Fixed == AJTableColumnFixedType.Right)
                .Select(c => c.CreateColumn()));

            UpdateFixedDataGridWidth();

            var ct = new AJTableColumnSettingDrawerContent();
            var dc = new AJTableColumnSettingDrawerContentViewModel
            {
                Columns = Columns
            };
            dc.ColumnVisibleChange += (s, e) =>
            {
                ExecuteColumnVisibleChangeCmd(e);
            };
            ct.DataContext = dc;
            DrawerHst.RightDrawerContent = ct;
        }

        public static DependencyProperty RowsProperty =
            DependencyProperty.Register(nameof(Rows), typeof(IEnumerable<object>), typeof(AJTable), new PropertyMetadata(new List<AJTableRowItem>(), RowsPropertyChanged));


        public IEnumerable<object> Rows
        {
            get
            {
                return (IEnumerable<object>)GetValue(RowsProperty);
            }
            set
            {
                SetValue(RowsProperty, value == null ? null : value.Select(p => new AJTableRowItem
                {
                    Data = p
                }).ToList());
            }
        }

        private static void RowsPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender is AJTable dataGrid)
            {
                dataGrid.RowsPropertyChanged(e);
            }
        }

        private void RowsPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            _mainTableRowHeightArray.Clear();
            _fxiedTableRowHeightArray.Clear();

            if (Rows == null || !Rows.Any())
            {
                return;
            }

            UpdateColumnBindings(ref DG_Table, AJTableColumnFixedType.Left);
            UpdateColumnBindings(ref DG_Fixed, AJTableColumnFixedType.Right);

            _mainScrollViewer = DG_Table.GetFirstVisualChild<ScrollViewer>();
            _fixedScrollViewer = DG_Fixed.GetFirstVisualChild<ScrollViewer>();

            if (DG_Fixed.Columns.Count > 0 && _mainScrollViewer != null)
            {
                _mainScrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
            }
        }

        private void UpdateColumnBindings(ref DataGrid dg, AJTableColumnFixedType type)
        {
            var props = (Rows.First() as AJTableRowItem).Data.GetType().GetRuntimeProperties();

            var styleCenter = new Style(typeof(TextBlock));
            //styleCenter.Setters.Add(new Setter(TextBlock.HorizontalAlignmentProperty, HorizontalAlignment.Center));
            styleCenter.Setters.Add(new Setter(TextBlock.VerticalAlignmentProperty, VerticalAlignment.Center));
            if (type == AJTableColumnFixedType.Left)
            {
                dg.FrozenColumnCount += Columns.Count(p => p.Fixed == AJTableColumnFixedType.Left);
            }

            foreach (var column in dg.Columns)
            {
                if (column is AJDataGridTextColumn col)
                {
                    if (col.Config == null)
                    {
                        continue;
                    }
                    var prop = props
                    .FirstOrDefault(p => p.Name.Equals(col.Config.DataIndex, StringComparison.OrdinalIgnoreCase));

                    if (prop != null && !string.IsNullOrWhiteSpace(col.Config.DataIndex))
                    {
                        var bindExpStr = $"{nameof(AJTableRowItem.Data)}.{col.Config.DataIndex}";
                        if (!string.IsNullOrWhiteSpace(col.Config.ExtraDataIndex))
                        {
                            bindExpStr += $".{col.Config.ExtraDataIndex}";
                        }
                        var binding = new Binding(bindExpStr);
                        if (col.Config.Formatter != null)
                        {
                            binding.Converter = new AJTableColumnConverter();
                            binding.ConverterParameter = col.Config.Formatter;
                        }
                        if (prop.PropertyType == typeof(DateTime) || prop.PropertyType == typeof(DateTime?))
                        {
                            binding.StringFormat = "yyyy-MM-dd HH:mm:ss";
                        }

                        col.Binding = binding;
                    }

                    col.ElementStyle = styleCenter;
                }

                if (column is AJDataGridTemplateColumn templateCol)
                {
                    if (templateCol.Config == null)
                    {
                        continue;
                    }
                    var template = TryFindResource(templateCol.Config.CustomTemplate.Key);
                    if (template != null)
                    {
                        templateCol.CellTemplate = template as DataTemplate;
                    }
                }

            }
        }

        #region Events

        public class ColumnVisibleChangeEventArgs : EventArgs
        {
            public AJTableColumnItem ColumnItem { get; set; }
        }

        public event EventHandler<DataGridRowEventArgs> LoadingRow;

        #endregion

        private DelegateCommand<SelectionChangedEventArgs> _pageSizeChangedCmd;
        public DelegateCommand<SelectionChangedEventArgs> PageSizeChangedCmd =>
            _pageSizeChangedCmd ?? (_pageSizeChangedCmd = new DelegateCommand<SelectionChangedEventArgs>(ExecutePageSizeChangedCmd));

        void ExecutePageSizeChangedCmd(SelectionChangedEventArgs parameter)
        {
            parameter.Handled = true;
            if (parameter.OriginalSource is ComboBox cb && cb.SelectedItem != null)
            {
                var newPageSize = (int)cb.SelectedItem;
                if (this.Pagination.PageSize == newPageSize)
                {
                    return;
                }
                Pagination.PageSize = newPageSize;

                GetListCmd.Execute(false);
            }
        }

        private DelegateCommand<bool?> _executeGetListCmd;
        public DelegateCommand<bool?> GetListCmd => _executeGetListCmd ??= new DelegateCommand<bool?>(ExecuteGetListCmd);

        async void ExecuteGetListCmd(bool? isExport)
        {
            await _fetchLocker.WaitAsync();

            AllSelectionModel.Checked = false;
            AllSelectionModel.SelectedCount = 0;

            if (FetchOptions != null && FetchOptions.Handle != null)
            {
                DgHst_Loading.IsOpen = true;
                FormConfig.IsExport = isExport.GetValueOrDefault();

                try
                {
                    var ret = await FetchOptions.Handle(FormConfig, Pagination);
                    Pagination.Total = ret.Total;
                    Rows = ret.Rows;
                }
                catch (FriendlyException e)
                {
                    AJCommonDialog.ShowDialog(new AJCommonDialogViewModel.AJCommonDialogParams
                    {
                        Title = e.Title,
                        Message = e.Message,
                    });
                }
                catch (Exception e)
                {
                    AJCommonDialog.ShowDialog(new AJCommonDialogViewModel.AJCommonDialogParams
                    {
                        Title = "提示",
                        Message = $"获取列表失败:{e.Message}",
                        Detail = e.StackTrace
                    });
                }
                finally
                {
                    DgHst_Loading.IsOpen = false;
                    _fetchLocker.Release();
                }

            }
        }

        private List<DataGrid> _dataGrids;
        private ScrollViewer _mainScrollViewer;
        private ScrollViewer _fixedScrollViewer;

        public AJTableAllSelectionModel AllSelectionModel { get; set; }

        public AJTable()
        {
            _fetchLocker = new SemaphoreSlim(1, 1);

            AllSelectionModel = new AJTableAllSelectionModel();

            InitializeComponent();
            _dataGrids = new List<DataGrid> { DG_Table, DG_Fixed };

            DG_Table.Loaded += (s, e) =>
            {
                UpdateDataGridColumnHeaderHeight();
            };

            DG_Fixed.Loaded += (s, e) =>
            {
                UpdateDataGridColumnHeaderHeight();
            };

            UC_ExportProgress.DataContext = new AJTableExportProgressViewModel();

            var eventAggregator = Prism.Ioc.ContainerLocator.Current.Resolve<IEventAggregator>();

            eventAggregator.GetEvent<AJGlobalExceptionResolvedEvent>().Subscribe(() => DgHst_Loading.IsOpen = false);
        }

        private void UpdateDataGridColumnHeaderHeight()
        {
            var left = DG_Table.GetFirstVisualChild<DataGridColumnHeadersPresenter>()?.ActualHeight;
            var right = DG_Fixed.GetFirstVisualChild<DataGridColumnHeadersPresenter>()?.ActualHeight;
            var max = left - right > 0 ? left : right;
            if (max > 0)
            {
                DG_Table.ColumnHeaderHeight = DG_Fixed.ColumnHeaderHeight = max.GetValueOrDefault();
            }

        }

        private void CreateRowSelectionColumn()
        {
            if (RowSelection == null)
            {
                return;
            }

            AllSelectionModel.Visibility = Visibility.Visible;

            var selectionColumn = new AJDataGridCheckBoxTemplateColumn
            {
                Width = new DataGridLength(60, DataGridLengthUnitType.SizeToCells, 48, 48),
                Visibility = Visibility.Visible,
                CellTemplate = TryFindResource("Selection") as DataTemplate,
                HeaderTemplate = TryFindResource("Selection_Header") as DataTemplate,
            };

            DG_Table.Columns.Insert(0, selectionColumn);
            DG_Table.FrozenColumnCount += 1;
        }

        public void Refresh(bool reset)
        {
            SearchCmd.Execute(reset.ToString());
        }

        public void ExecuteExport()
        {
            ExportButton_Click(Btn_Export, new RoutedEventArgs());
        }

        private DelegateCommand<AJTablePageItem> _pageItemCheckedCmd;
        public DelegateCommand<AJTablePageItem> PageItemCheckedCmd => _pageItemCheckedCmd ??= new DelegateCommand<AJTablePageItem>(ExecutePageItemCheckedCmd);

        void ExecutePageItemCheckedCmd(AJTablePageItem parameter)
        {
            if (parameter.PageNumber.Equals("···"))
            {
                var prev = parameter.ToolTip.Contains('前');
                var current = prev
                    ? new int[] { 1, Pagination.Current - 5 }.Max()
                    : new int[] { Pagination.Total, Pagination.Current + 5 }.Min();

                Pagination.Current = current;
                return;
            }
            Pagination.Current = Convert.ToInt32(parameter.PageNumber);
            ExecuteGetListCmd(null);
        }

        private DelegateCommand<string> _prevOrNextPageChangeCmd;
        public DelegateCommand<string> PrevOrNextPageChangeCmd => _prevOrNextPageChangeCmd ??= new DelegateCommand<string>(ExecutePrevOrNextPageChangeCmd);

        void ExecutePrevOrNextPageChangeCmd(string parameter)
        {
            var changed = false;
            var prev = parameter.Contains('上');
            if (prev)
            {
                if (Pagination.CanPrevPage)
                {
                    Pagination.Current -= 1;
                    changed = true;
                }
            }
            else
            {
                if (Pagination.CanNextPage)
                {
                    Pagination.Current += 1;
                    changed = true;
                }
            }

            if (changed)
            {
                ExecuteGetListCmd(null);
            }
        }

        private DelegateCommand<KeyEventArgs> _jumpToPageCmd;
        public DelegateCommand<KeyEventArgs> JumpToPageCmd => _jumpToPageCmd ??= new DelegateCommand<KeyEventArgs>(ExecuteJumpToPageCmd);

        void ExecuteJumpToPageCmd(KeyEventArgs parameter)
        {
            if (parameter.Key == Key.Enter)
            {
                var page = TextBox_PageNum.Text.TryGetInt();
                if (page < 1)
                {
                    page = 1;
                }
                if (page > Pagination.TotalPages)
                {
                    page = Pagination.TotalPages;
                }
                if (page == Pagination.Current)
                {
                    return;
                }
                Pagination.Current = page;
                TextBox_PageNum.Clear();
                ExecuteGetListCmd(null);

            }
        }

        private DelegateCommand<string> _searchCmd;
        public DelegateCommand<string> SearchCmd => _searchCmd ??= new DelegateCommand<string>(ExecuteSearchCmd);

        void ExecuteSearchCmd(string parameter)
        {
            DrawerHst.IsTopDrawerOpen = false;

            var refresh = Convert.ToBoolean(parameter);
            if (refresh)
            {
                FormConfig.Reset();
            }

            ExecuteGetListCmd(null);

        }

        private void ImportButton_Click(object sender, EventArgs e)
        {
            var app = Application.Current as PrismApplicationBase;
            var dialogSvc = app.Container.Resolve<IDialogService>();

            var @params = new DialogParameters
            {
                { "data", ImportOptions },
            };

            dialogSvc.ShowDialog("ImportExcelDialog", @params, r =>
            {
                if (r.Result == ButtonResult.OK)
                {
                    Refresh(true);
                }
            });
        }

        private async void ExportButton_Click(object sender, RoutedEventArgs e)
        {
            var exportProgress = UC_ExportProgress.DataContext as AJTableExportProgressViewModel;

            if (!DG_Table.HasItems)
            {
                exportProgress.Current = 0;
                exportProgress.Total = 100;
                exportProgress.Text = "没有任何数据需要导出";
                exportProgress.Loading = true;

                await Task.Delay(1500);

                exportProgress.Loading = false;

                return;
            }

            exportProgress.Current = 0;
            exportProgress.Total = 100;
            exportProgress.Text = "导出中...";
            exportProgress.Loading = true;

            var worker = new BackgroundWorker
            {
                WorkerReportsProgress = true
            };

            var pageCfg = new AJTablePagination
            {
                Current = 1,
                PageSize = 10,
            };
            var rows = new List<object>();

            var handle = FetchOptions.Handle;
            var formCfg = FormConfig;
            formCfg.IsExport = true;

            var fileName = $"{FetchOptions.ExportFileName}_{DateTime.Now.ToString("yyyyMMddHHmmss")}";
            var exportWithCurrentColumns = FetchOptions.ExportWithCurrentColumns;
            var exportImage = FetchOptions.ExportWithImage;

            worker.DoWork += (s, e) =>
            {
                while (true)
                {
                    var listTask = handle(formCfg, pageCfg);

                    listTask.Wait();

                    var list = listTask.Result;

                    pageCfg.Total = list.Total;

                    if (list.Rows.Any())
                    {
                        rows.AddRange(list.Rows);
                    }

                    if (!list.HasNext)
                    {
                        worker.ReportProgress(pageCfg.Current, list.Total);
                        Thread.Sleep(600);
                        break;
                    }

                    pageCfg.Current++;
                    worker.ReportProgress(pageCfg.Current, list.Total);
                    Thread.Sleep(600);
                }

            };
            worker.ProgressChanged += (s, e) =>
            {
                exportProgress.Total = (int)e.UserState;
                exportProgress.Current = rows.Count;
                exportProgress.Text = $"正在导出...{exportProgress.Current}/{exportProgress.Total}";
            };
            worker.RunWorkerCompleted += async (s, e) =>
            {
                // 导出完毕一定要设置成false
                FormConfig.IsExport = false;
                exportProgress.Text = $"选择保存位置...";
                exportProgress.Current = rows.Count;
                Thread.Sleep(1500);

                var fileDialog = new Microsoft.Win32.SaveFileDialog
                {
                    CreatePrompt = true,
                    OverwritePrompt = true,
                    AddExtension = true,
                    DefaultExt = ".xlsx",
                    Filter = "excel 文件（.xlsx）|*.xlsx",
                    FileName = fileName,
                };

                if ((fileDialog.ShowDialog()).GetValueOrDefault())
                {
                    var tempColumns = Columns.Where(p => p.IsExport)
                    .Select(p => new
                    {
                        p.DataIndex,
                        p.Formatter,
                        p.Title,
                        p.CustomTemplate
                    }).ToList();

                    exportProgress.Text = $"正在写入...";

                    var result = await Task.Run(() =>
                    {
                        if (exportWithCurrentColumns)
                        {
                            var exportItems = new List<IList<AJExportItem>>();
                            foreach (var row in rows)
                            {
                                var columnValues = new List<AJExportItem>();
                                var index = 0;
                                var props = row.GetType().GetRuntimeProperties();
                                foreach (var column in tempColumns)
                                {
                                    var prop = props.FirstOrDefault(p => p.Name == column.DataIndex);
                                    var val = prop?.GetValue(row);
                                    if (column.Formatter != null && column.Formatter.Handler != null)
                                    {
                                        val = column.Formatter.Handler(val);
                                    }
                                    var item = new AJExportItem
                                    {
                                        Title = column.Title,
                                        Index = index,
                                        IsImage = (column.CustomTemplate?.IsImage).GetValueOrDefault(),
                                        Value = val
                                    };
                                    // 如果没有启用导出图片， 并且当前列是图片列， 则清空值
                                    if (!exportImage && item.IsImage)
                                    {
                                        item.Value = string.Empty;
                                    }
                                    columnValues.Add(item);
                                    index++;
                                }

                                exportItems.Add(columnValues);
                            }

                            return AJExport.CreateExcel(exportItems, fileDialog.FileName, fileName);
                        }
                        return AJExport.CreateExcel(rows, fileDialog.FileName, fileName,false, exportImage);
                    });
                    if (!result.Success)
                    {
                        exportProgress.Text = $"导出失败!{result.Message}";
                        Thread.Sleep(3000);
                    }
                    else
                    {
                        exportProgress.Text = $"导出成功!";
                        Thread.Sleep(1500);
                    }

                }

                exportProgress.Loading = false;
            };

            worker.RunWorkerAsync();
        }

        private DelegateCommand _advFilterCmd;
        public DelegateCommand AdvFilterCmd => _advFilterCmd ??= new DelegateCommand(ExecuteAdvFilterCmd);

        void ExecuteAdvFilterCmd()
        {
            DrawerHst.IsTopDrawerOpen = true;
        }

        private void SettingButton_Click(object sender, RoutedEventArgs e)
        {
            DrawerHst.IsRightDrawerOpen = true;
        }

        private List<double> _mainTableRowHeightArray = new List<double>();

        private void DG_Table_LoadingRow(object sender, DataGridRowEventArgs e)
        {
            if (EnableRowIndex)
            {
                e.Row.Header = e.Row.GetIndex() + 1;
            }
            e.Row.Loaded += (s, _) =>
            {
                _mainTableRowHeightArray.Add(((DataGridRow)s).ActualHeight);
                AutoRowHeight();
            };
            e.Row.MouseEnter += (_, e) =>
            {
                SyncRowBackground(ref DG_Fixed, e, true);
            };
            e.Row.MouseLeave += (_, e) =>
            {
                SyncRowBackground(ref DG_Fixed, e, false);
            };

            e.Row.Selected += (_, e) =>
            {
                SyncRowSelected(ref DG_Fixed, e, true);
            };

            e.Row.Unselected += (_, e) =>
            {
                SyncRowSelected(ref DG_Fixed, e, false);
            };

            LoadingRow?.Invoke(DG_Table, e);
        }

        private List<double> _fxiedTableRowHeightArray = new List<double>();
        private void DG_Fixed_LoadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.Loaded += (s, _) =>
            {
                _fxiedTableRowHeightArray.Add(((DataGridRow)s).ActualHeight);
                AutoRowHeight();
            };
            e.Row.MouseEnter += (_, e) =>
            {
                SyncRowBackground(ref DG_Table, e, true);
            };
            e.Row.MouseLeave += (_, e) =>
            {
                SyncRowBackground(ref DG_Table, e, false);
            };
            e.Row.Selected += (_, e) =>
            {
                SyncRowSelected(ref DG_Table, e, true);
            };

            e.Row.Unselected += (_, e) =>
            {
                SyncRowSelected(ref DG_Table, e, false);
            };

            LoadingRow?.Invoke(DG_Fixed, e);
        }

        private void SyncRowSelected(ref DataGrid dg, RoutedEventArgs e, bool selected)
        {
            var currentRow = (DataGridRow)e.Source;
            var index = currentRow.GetIndex();
            if (index != -1)
            {
                if (dg.ItemContainerGenerator.ContainerFromIndex(index) is DataGridRow targetRow)
                {
                    var cur = (AJTableRowItem)currentRow.Item;
                    var tar = (AJTableRowItem)targetRow.Item;

                    cur.Selected = selected;
                    tar.Selected = selected;

                    dg.SelectedIndex = -1;
                }
            }
        }

        private void SyncRowBackground(ref DataGrid dg, MouseEventArgs e, bool enter)
        {
            var currentRow = (DataGridRow)e.Source;
            var index = currentRow.GetIndex();
            if (index != -1)
            {
                if (dg.ItemContainerGenerator.ContainerFromIndex(index) is DataGridRow targetRow)
                {
                    targetRow = dg.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow;
                    ((AJTableRowItem)currentRow.Item).IsMousehover = enter;
                    ((AJTableRowItem)targetRow.Item).IsMousehover = enter;
                }
            }

        }

        private void AutoRowHeight()
        {
            var array = _mainTableRowHeightArray.Concat(_fxiedTableRowHeightArray).Distinct();
            if (array.Any())
            {
                var max = array.Max();
                if (max > 0)
                {
                    DG_Table.RowHeight = DG_Fixed.RowHeight = max;
                }
            }
        }

        private DelegateCommand<AJTableColumnItem> _columnVisibleChangeCmd;
        public DelegateCommand<AJTableColumnItem> ColumnVisibleChangeCmd => _columnVisibleChangeCmd ??= new DelegateCommand<AJTableColumnItem>(ExecuteColumnVisibleChangeCmd);

        void ExecuteColumnVisibleChangeCmd(AJTableColumnItem columnItem)
        {
            var formItem = FormConfig.Schemas.FirstOrDefault(p => p.Field == columnItem.DataIndex);
            if (formItem != null)
            {
                formItem.Visible = columnItem.Visible ? Visibility.Visible : Visibility.Collapsed;
            }

            var hasChange = false;
            var hasFixedColChange = false;

            foreach (var dg in _dataGrids)
            {
                foreach (var item in dg.Columns)
                {
                    if (item is AJDataGridTextColumn textCol)
                    {
                        if (textCol.ColumnKey == columnItem.DataIndex)
                        {
                            textCol.Visibility = columnItem.Visible ? Visibility.Visible : Visibility.Collapsed;
                            if (columnItem.Fixed == AJTableColumnFixedType.Right)
                            {
                                hasFixedColChange = true;
                            }
                            hasChange = true;
                            break;
                        }
                    }
                    if (item is AJDataGridTemplateColumn tplCol)
                    {
                        if (tplCol.ColumnKey == columnItem.DataIndex)
                        {
                            tplCol.Visibility = columnItem.Visible ? Visibility.Visible : Visibility.Collapsed;
                            if (columnItem.Fixed == AJTableColumnFixedType.Right)
                            {
                                hasFixedColChange = true;
                            }
                            hasChange = true;
                            break;
                        }
                    }
                }
            }

            if (hasFixedColChange)
            {
                // 重算固定表格宽度
                UpdateFixedDataGridWidth();
            }

            if (hasChange && Columns.Any(p => p.IsSummaryField))
            {
                ExecuteGetListCmd(null);
            }

        }

        private void DG_Table_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            _fixedScrollViewer?.ScrollToVerticalOffset(e.VerticalOffset);
        }

        private void DG_Fixed_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            _mainScrollViewer?.ScrollToVerticalOffset(e.VerticalOffset);
        }

        private void UpdateFixedDataGridWidth()
        {
            if (DG_Fixed.Columns.Count > 0)
            {
                ColumnDef_FixedGrid.Width = new GridLength(DG_Fixed.Columns
                    .Where(p => p.Visibility == Visibility.Visible).Sum(p => p.Width.Value));
            }
            else
            {
                ColumnDef_FixedGrid.Width = new GridLength(0);
            }
        }

        private DelegateCommand<object> _rowCheckedChangeCmd;
        public DelegateCommand<object> RowCheckedChangeCmd => _rowCheckedChangeCmd ??= new DelegateCommand<object>(ExecuteRowCheckedChangeCmd);

        void ExecuteRowCheckedChangeCmd(object parameter)
        {
            if (parameter is AJTableRowItem rowItem)
            {
                var checkedRows = Rows.Select(p => (AJTableRowItem)p)
                .Where(p => p.Checked).Select(p => p.Data).AsEnumerable();

                AllSelectionModel.SelectedCount = (checkedRows?.Count()).GetValueOrDefault();

                var allChecked = AllSelectionModel.SelectedCount == Rows.Count();

                if (allChecked)
                {
                    AllSelectionModel.Checked = true;
                    RowSelection.OnSelectAllHandler?.Invoke(checkedRows);
                    RowSelection.OnChangeHandler?.Invoke(checkedRows);
                    return;
                }
                else
                {
                    AllSelectionModel.Checked = AllSelectionModel.SelectedCount > 0 ? null : false;
                }

                RowSelection.OnSelectHandler?.Invoke(rowItem.Data, rowItem.Checked);

                RowSelection.OnChangeHandler?.Invoke(checkedRows);
            }
        }

        private void CheckBox_All_CheckedChanged(object sender, RoutedEventArgs e)
        {
            var @checked = ((CheckBox)sender).IsChecked;
            if (!@checked.HasValue)
            {
                return;
            }
            foreach (var dg in _dataGrids)
            {
                foreach (AJTableRowItem item in dg.Items)
                {
                    item.Checked = @checked.GetValueOrDefault();
                }
            }
        }


    }
}
